package com.monochromebytes.mononet.test.network;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Timer;
import java.util.TimerTask;

import com.monochromebytes.mononet.stub.ObjectListener;
import com.monochromebytes.mononet.stub.Serializer;
import com.monochromebytes.mononet.stub.Stub;
import com.monochromebytes.mononet.stub.StubArbiter;
import com.monochromebytes.mononet.stub.StubSocket;
import com.monochromebytes.mononet.virtual.ConnectionID;
import com.monochromebytes.mononet.virtual.VirtualAddress;

import com.monochromebytes.mononet.test.Updatable;

public abstract class NetworkController implements StubArbiter, ObjectListener, Updatable {

    protected static ConnectionID id = new ConnectionID(1234567890);

    protected final StubSocket    socket;
    private final Serializer      serializer;
    private final Timer           timer;

    protected int                 currentNumberOfSentObjects;
    private int                   numberOfSentObjects;
    private int                   currentNumberOfReceivedObjects;
    private int                   numberOfReceivedObjects;
    private int                   currentNumberOfLostObjects;
    private int                   numberOfLostObjects;
    private int                   currentNumberOfAcknowledgedObjects;
    private int                   numberOfAcknowledgedObjects;

    public NetworkController(InetSocketAddress localAddress) throws IOException {
        this.serializer = new SimpleSerializer();

        this.socket = new StubSocket(localAddress, this);
        this.socket.open();

        this.timer = new Timer();
        this.timer.schedule(new TimerTask() {
            @Override
            public void run() {
                numberOfSentObjects = currentNumberOfSentObjects;
                currentNumberOfSentObjects = 0;
                numberOfReceivedObjects = currentNumberOfReceivedObjects;
                currentNumberOfReceivedObjects = 0;
                numberOfLostObjects = currentNumberOfLostObjects;
                currentNumberOfLostObjects = 0;
                numberOfAcknowledgedObjects = currentNumberOfAcknowledgedObjects;
                currentNumberOfAcknowledgedObjects = 0;
            }
        }, 1000, 1000);
    }

    @Override
    public boolean accept(VirtualAddress address) {
        ConnectionID id = address.getConnectionID();
        return id.equals(NetworkController.id);
    }

    @Override
    public Serializer getSerializer(VirtualAddress address) {
        return this.serializer;
    }

    @Override
    public void receiveObject(Object object, Stub stub) {
        this.currentNumberOfReceivedObjects++;
    }

    @Override
    public void lostObject(Object object, Stub stub, int timeToLive) {
        this.currentNumberOfLostObjects++;
    }

    @Override
    public void acknowledgedObject(Object object, Stub stub, int timeToLive, int roundTripTime) {
        this.currentNumberOfAcknowledgedObjects++;
    }

    public int getNumberOfSentPackets() {
        return this.numberOfSentObjects;
    }

    public int getNumberOfReceivedPackets() {
        return this.numberOfReceivedObjects;
    }

    public int getNumberOfLostPackets() {
        return this.numberOfLostObjects;
    }

    public int getNumberOfAcknowledgedPackets() {
        return this.numberOfAcknowledgedObjects;
    }
}
